package com.arthas.arthasforsba.app.configuration;


import com.arthas.arthasforsba.utils.Sm3Util;
import de.codecentric.boot.admin.server.config.AdminServerProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;

/**
 * @author dingling
 * @desc
 * @date 2023-07-04 17:30
 **/

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    /**
     * 自定义用户认证逻辑
     */

    private UserDetailsService userDetailsService;

    private final String adminContextPath;

    @Autowired
    private ArthasProperties arthasProperties;

    public SecurityConfig(AdminServerProperties adminServerProperties) {
        this.adminContextPath = adminServerProperties.getContextPath();
    }

    @Autowired
    private void setUserDetailsService(UserDetailsService userDetailsService){
        this.userDetailsService = userDetailsService;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        // @formatter:off
        SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
        successHandler.setTargetUrlParameter("redirectTo");
        successHandler.setDefaultTargetUrl(adminContextPath + "/");

        // allow iframe
        if (arthasProperties.isEnableIframeSupport()) {
            http.headers().frameOptions().disable();
        }

        http.authorizeRequests()
                //Grants public access to all static assets and the login page.
                .antMatchers(adminContextPath + "/assets/**").permitAll()
                .antMatchers(adminContextPath + "/login").permitAll()
                .antMatchers(adminContextPath + "/api/**").permitAll()
                .anyRequest().authenticated()//	Every other request must be authenticated.
                .and()
                //Configures login and logout.
                .formLogin().loginPage(adminContextPath + "/login").successHandler(successHandler).and()
                .logout().logoutUrl(adminContextPath + "/logout").and()
                //Enables HTTP-Basic support. This is needed for the Spring Boot Admin Client to register.
                .httpBasic().and()
                .csrf()
                //	Enables CSRF-Protection using Cookies
                .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
                .ignoringAntMatchers(
                        //	Disables CRSF-Protection the endpoint the Spring Boot Admin Client uses to register.
                        adminContextPath + "/instances",
                        //Disables CRSF-Protection for the actuator endpoints.
                        adminContextPath + "/actuator/**",
                        adminContextPath + "/api/files/**"
                );
    }


    /**
     * sm3加密实现
     */
    @Bean
    public PasswordEncoder sm4PasswordEncoder()
    {
        return new PasswordEncoder() {
            @Override
            public String encode(CharSequence charSequence) {
                return Sm3Util.encrypt(charSequence);
            }

            @Override
            public boolean matches(CharSequence charSequence, String s) {
                return Sm3Util.verify(charSequence,s);
            }
        };
    }

    /**
     * 身份认证接口
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception
    {
        auth.userDetailsService(userDetailsService).passwordEncoder(sm4PasswordEncoder());
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        super.configure(web);
    }
}
